package top.jolyoulu.modules.poimodule.excel.reader.sax;

import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.util.XMLHelper;
import org.apache.poi.xssf.eventusermodel.XSSFReader;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
import top.jolyoulu.modules.poimodule.excel.annotation.ExcelImport;
import top.jolyoulu.modules.poimodule.excel.reader.AbsExcelReaderHandler;
import top.jolyoulu.modules.poimodule.excel.reader.DefExcelReaderHandler;

import java.io.*;
import java.time.LocalDate;
import java.util.*;

/**
 * @Author: JolyouLu
 * @Date: 2023/1/20 15:11
 * @Description Excel读取工具
 */
@Slf4j
public class SaxExcelReader<T> {

    private AbsExcelReaderHandler<T> handler;

    private SaxExcelReader(Class<T> dataType) {
        this.handler = new DefExcelReaderHandler<T>(dataType);
    }

    /**
     * 初始化一个DefaultExcelReader
     * @param dataType 需要识别的类
     * @return SaxExcelReader
     */
    public static <T> SaxExcelReader<T> of(Class<T> dataType){
        return new SaxExcelReader<>(dataType);
    }

    /**
     * 设置需要读取的sheet
     * @param index sheet的下标，1开始
     * @return SaxExcelReader
     */
    public SaxExcelReader<T> sheet(int index) {
        this.handler.setSheetIndex(index);
        this.handler.setStartRow(2);
        return this;
    }

    /**
     * 设置需要读取的sheet，与开始读取的行号
     * @param index sheet的下标，0开始
     * @param startRow 开始读取的行号，1开始
     * @return SaxExcelReader
     */
    public SaxExcelReader<T> sheet(int index, int startRow) {
        this.handler.setSheetIndex(index);
        this.handler.setStartRow(startRow);
        return this;
    }

    /**
     * 简单读取，读取Excel中数据
     * @param inputStream excel文件流
     * inputStream流使用完毕后需要自己手动关闭
     */
    public List<T> read(InputStream inputStream){
        //解压Sax
        try(OPCPackage pkg = OPCPackage.open(inputStream)) {
            //开始执行读取
            XSSFReader xssfReader = new XSSFReader(pkg);
            XMLReader parser = XMLHelper.newXMLReader();
            parser.setContentHandler(new SaxExcelReaderHandler(xssfReader.getSharedStringsTable(), handler));
            try (InputStream sheet = xssfReader.getSheetsData().next()) {
                InputSource sheetSource = new InputSource(sheet);
                parser.parse(sheetSource);
            }
        } catch (Exception e) {
            log.error("SaxExcelReader读取数据失败",e);
        }
        return handler.getData();
    }

    /**
     * 简单读取，读取Excel中数据
     * @param file 文件
     */
    public List<T> read(File file){
        try(FileInputStream inputStream = new FileInputStream(file)) {
            return read(inputStream);
        } catch (Exception e) {
            log.error("SaxExcelReader读取数据失败",e);
        }
        return handler.getData();
    }
}
